//
//  FPluginCenter.m
//  Foundation
//
//  Created by 三井 on 2019/10/18.
//

#import "FPluginCenter.h"
#import "FPluginStore.h"

@interface FPluginCenter ()

@property (nonatomic, strong) NSMutableSet<Class<FPlugin>> *pluginClassSet; /// 插件类声明集合

@end

@implementation FPluginCenter

+ (instancetype)sharedInstance {
    static dispatch_once_t onceToken;
    static FPluginCenter *inst = nil;
    dispatch_once(&onceToken, ^{
        inst = [[FPluginCenter alloc] init];
    });
    return inst;
}

- (void)registerPlugin:(Class<FPlugin>)pluginClass {
    [self.pluginClassSet addObject:pluginClass];
}

- (NSArray<id<FPlugin>> *)loadPluginFor:(NSString *)hostIdentifier {
    NSMutableArray *mArr = [NSMutableArray array];
    [self.pluginClassSet enumerateObjectsUsingBlock:^(Class<FPlugin>  _Nonnull obj, BOOL * _Nonnull stop) {
        if ([self shouldLoad:obj forHost:hostIdentifier]) {
            id<FPlugin> plugin = [[(Class)obj alloc] init];
            [mArr addObject:plugin];
        }
    }];
    
    return [mArr sortedArrayUsingComparator:^NSComparisonResult(id<FPlugin>  _Nonnull obj1, id<FPlugin>  _Nonnull obj2) {
        NSInteger pri1 = 0;
        if ([obj1 respondsToSelector:@selector(priority)]) {
            pri1 = obj1.priority;
        }
        
        NSInteger pri2 = 0;
        if ([obj2 respondsToSelector:@selector(priority)]) {
            pri2 = obj2.priority;
        }
        
        return pri1 < pri2 ? NSOrderedAscending : NSOrderedDescending;
    }];;
}

#pragma mark - Private
- (BOOL)shouldLoad:(Class<FPlugin>)plugin forHost:(NSString *)host {
    if ([self.delegate respondsToSelector:@selector(shouldLoad:forHost:)] && ![self.delegate shouldLoad:[plugin identifier] forHost:host]) {
        return NO;
    }
    if (![[plugin hostIdentifiers] containsObject:host]) {
        return NO;
    }
    return YES;
}

- (NSMutableSet<Class<FPlugin>> *)pluginClassSet {
    if (!_pluginClassSet) {
        _pluginClassSet = [NSMutableSet set];
    }
    return _pluginClassSet;
}

@synthesize pluginStore = _pluginStore;
- (FPluginStore *)pluginStore {
    if (!_pluginStore) {
        _pluginStore = [[FPluginStore alloc] init];
    }
    return _pluginStore;
}
@end
